#include "app_buffer.h"
#include <stdlib.h>
#include <string.h>
#include "log/log.h"



static SubBuffer *sub_buffer_init(int size)
{
    SubBuffer *sub_buffer = (SubBuffer *)malloc(sizeof(SubBuffer));
    sub_buffer->ptr = (char *)malloc(size);
    sub_buffer->size = size;
    sub_buffer->len = 0;

    return sub_buffer;
}

Buffer *app_buffer_init(int size)
{
    Buffer *buffer = (Buffer *)malloc(sizeof(Buffer));

    buffer->sub_buffers[0] = sub_buffer_init(size);
    buffer->sub_buffers[1] = sub_buffer_init(size);

    buffer->read_index = 0;
    buffer->write_index = 1;

    // 初始化读/写锁
    pthread_mutex_init(&buffer->read_lock, NULL);
    pthread_mutex_init(&buffer->write_lock, NULL);

    return buffer;
}

void app_buffer_free(Buffer *buffer)
{
    free(buffer->sub_buffers[0]->ptr);
    free(buffer->sub_buffers[1]->ptr);
    free(buffer->sub_buffers[0]);
    free(buffer->sub_buffers[1]);
    free(buffer);
}

int app_buffer_write(Buffer *buffer, char *data, int len)
{
    if (len > 255) { // 后面用一个字节存储长度值
        log_error("写入数据的长度不能超过255");
        return -1;
    }

    // 加写锁
    log_debug("写入数据前， 加写锁");
    pthread_mutex_lock(&buffer->write_lock);

    // 得到写缓冲区
    SubBuffer *w_buffer = buffer->sub_buffers[buffer->write_index];
    // 检查缓冲区是否还有足够的空间
    if (w_buffer->size-w_buffer->len < len + 1) {
        log_error("缓冲区剩余空间不足");
        // 解写锁
        pthread_mutex_unlock(&buffer->write_lock);

        return -1;
    }

    // 先写入数据长度，再写入数据本身
    w_buffer->ptr[w_buffer->len] = len;
    memcpy(w_buffer->ptr+w_buffer->len+1, data, len);

    // 更新len
    w_buffer->len += len + 1;

    // 解写锁
    log_debug("写入数据后， 解写锁");
    pthread_mutex_unlock(&buffer->write_lock);

    return 0;
}

static void sub_buffer_swap(Buffer *buffer) {
    // 加写锁
    log_debug("切换读/写缓冲区前， 加写锁");
    pthread_mutex_lock(&buffer->write_lock);

    int temp = buffer->read_index;
    buffer->read_index = buffer->write_index;
    buffer->write_index = temp;
    // 解写锁
    log_debug("切换读/写缓冲区后， 解写锁");
    pthread_mutex_unlock(&buffer->write_lock);
}

int app_buffer_read(Buffer *buffer, char *data_buf, int buf_size)
{
    // 加读锁
    log_debug("读取数据前， 加读锁");
    pthread_mutex_lock(&buffer->read_lock);

    // 得到读缓冲区
    SubBuffer *r_buffer = buffer->sub_buffers[buffer->read_index];
    // 如果读缓冲区为空，切换读/写缓冲区， 如果还是空的，失败结束
    if (r_buffer->len == 0) {
        sub_buffer_swap(buffer);
        r_buffer = buffer->sub_buffers[buffer->read_index];
        if (r_buffer->len == 0) {
            log_error("读缓冲区为空");
            // 解读锁
            pthread_mutex_unlock(&buffer->read_lock);
            return -1;
        }
    }

    // 读取数据长度（第一个字节数据）len
    int len = r_buffer->ptr[0];
    log_debug("读取数据长度：%d", len);
    // 如果data_buf大小不够，失败结束
    if (buf_size < len) {
        log_error("data_buf大小不够");
        // 解读锁
        pthread_mutex_unlock(&buffer->read_lock);
        return -1;
    }
    // 读取后面len个字节数据到data_buf中
    memcpy(data_buf, r_buffer->ptr + 1, len);
    // 将后面未读取的数据移到起始位置
    memmove(r_buffer->ptr, r_buffer->ptr+1+len, r_buffer->len-len-1);

    // 更新读缓冲区的len
    r_buffer->len -= len + 1;

    // 解读锁
    log_debug("读取数据后， 解读锁");
    pthread_mutex_unlock(&buffer->read_lock);

    // 返回读取的数据长度
    return len;
}
